/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.resourceScaler;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.nudt.jCloud.infrastructure.Slot;
import org.nudt.jCloud.infrastructure.SlotType;
import org.nudt.jCloud.simulation.RequestData;
import org.nudt.jCloud.simulation.ScaleData;

public class ThresholdScaler extends ResourceScaler{
	private double upThreshold;
	private double downThreshold;
	
	public ThresholdScaler(double upThreshold, double downThreshold) {
		super();
		setUpThreshold(upThreshold);
		setDownThreshold(downThreshold);
	}

	@Override
	public void scaleResource(RequestData requestData, ScaleData scaleData) {
		Map<SlotType, Integer> requestLoad = requestData.requestLoad();
		Set<SlotType> requestType = requestLoad.keySet();
		Iterator<SlotType> requestTypeItr = requestType.iterator();
		while(requestTypeItr.hasNext()){
			SlotType slotType = requestTypeItr.next();
			int freeNum = 0;
			int busyNum = 0;
			if(getFrwk().getFreeSlots().get(slotType)!=null){
				freeNum = getFrwk().getFreeSlots().get(slotType).size();
			}
			if(getFrwk().getBusySlots().get(slotType)!=null){
				busyNum = getFrwk().getBusySlots().get(slotType).size();
			}
			int leasedNum = freeNum + busyNum;
			int detaNum = 0;
			if(leasedNum == 0){
				detaNum = requestLoad.get(slotType);
				scaleData.getToLeaseSlot().put(slotType, detaNum);
			}else{
				double curLoad = ((double)(requestLoad.get(slotType)+busyNum))/leasedNum;
				if(curLoad > upThreshold){
					detaNum = (int) Math.ceil((requestLoad.get(slotType)+busyNum)/upThreshold)-leasedNum;
					scaleData.getToLeaseSlot().put(slotType, detaNum);
				}else if(curLoad < downThreshold){
					detaNum = leasedNum - (int) Math.ceil((requestLoad.get(slotType)+busyNum)/downThreshold);
					List<Slot> slotList = getFrwk().releaseFreeSlot(slotType, detaNum);
					scaleData.getToReleaseSlot().put(slotType, slotList);
				}
			}
		}
		
	}

	public double getDownThreshold() {
		return downThreshold;
	}

	public void setDownThreshold(double downThreshold) {
		this.downThreshold = downThreshold;
	}

	public double getUpThreshold() {
		return upThreshold;
	}

	public void setUpThreshold(double upThreshold) {
		this.upThreshold = upThreshold;
	}

	@Override
	public void specialReset() {
		// TODO Auto-generated method stub
		
	}
	
}
